package ru.amse.tsyganov.jumleditor.model;


/**
 * A transition is a directed relationship between 
 * a source state vertex and a target state vertex.
 * 
 * @author Dmitry Tsyganov
 *
 */
public class Transition extends ModelElement {
	/**
	 * Designates the originating state vertex 
	 * (state or pseudostate) of the transition.
	 */
	private StateVertex source;
	
	/**
	 * Designates the target state vertex that 
	 * is reached when the transition is taken.
	 */
	private StateVertex target;
	
	private boolean guard = false;
	
	private String guardExpression = "";

	public Transition(
			StateVertex sourceVertex, 
			StateVertex targetVertex) {
		
		if (sourceVertex == null || targetVertex == null ||
				sourceVertex == targetVertex) {
			throw new IllegalArgumentException();
		}
		
		source = sourceVertex;
		target = targetVertex;
	}
	
	public StateVertex getSource() {
		assert source != null;
		return source;
	}

	public void setSource(StateVertex sourceVertex) {
		
		if (sourceVertex == null) {
			throw new IllegalArgumentException();
		}
		
		assert source.getOutgoing().contains(this);
		
		source.getOutgoing().remove(this);
		source = sourceVertex;
		source.getOutgoing().add(this);
		
		assert source.getOutgoing().contains(this);
	}

	public StateVertex getTarget() {
		assert target != null;
		return target;
	}

	public void setTarget(StateVertex targetVertex) {
		
		if (targetVertex == null) {
			throw new IllegalArgumentException();
		}
		
		assert target.getIncoming().contains(this);
		
		target.getIncoming().remove(this);
		target = targetVertex;
		target.getIncoming().add(this);
		
		assert target.getIncoming().contains(this);
	}
	
	public void removeBindings() {
		source.getOutgoing().remove(this);
		target.getIncoming().remove(this);
	}
	
	public void addBindings() {
		source.getOutgoing().add(this);
		target.getIncoming().add(this);
	}

	public boolean isGuard() {
		return guard;
	}

	public void setGuard(boolean guard) {
		this.guard = guard;
	}

	public String getGuardExpression() {
		return guardExpression;
	}

	public void setGuardExpression(String guardExpression) {
		this.guardExpression = guardExpression;
	}
}
